    #pragma once 

    #include<pthread.h>
    #include<iostream>
    #include<queue>
    #include<unistd.h>
    template <class T>
    class BlockQueue
    {
        static  const  int defalutnum =5 ;
    public:
        BlockQueue(int maxcap = defalutnum)
        :maxcap_(maxcap)
    
        {
           pthread_mutex_init(&mutex_, nullptr);
        pthread_cond_init(&c_cond_, nullptr);
        pthread_cond_init(&p_cond_, nullptr);
        }

       T  pop()
        {
                  //加锁
            pthread_mutex_lock(&mutex_) ;

            //队列为空，消费者等待
            while(q_.size()  ==  0) 
            {
                pthread_cond_wait(&c_cond_ ,&mutex_); //等待时是持有锁的，在调用的时候，自动释放锁，因为唤醒而返回的时候，重新持有锁
            }
                        //消费
                T out = q_.front() ;
                    q_.pop();

                        //消费完了，肯定可以进行生产， 所以唤醒生产者
                    pthread_cond_signal(&p_cond_) ;

               //解锁
            pthread_mutex_unlock(&mutex_) ;

                return out ;
        }

        void push( T & in) 
        {
            //加锁
            pthread_mutex_lock(&mutex_) ;
                //队列已满 ,生产者等待
                while(q_.size() ==maxcap_) // 做到防止线程被伪唤醒的情况
                {
                    pthread_cond_wait(&p_cond_,&mutex_) ;  //调用的时候，自动释放锁
                }

              

            q_.push(in) ;

              //队列未满，唤醒消费者
                pthread_cond_signal(&c_cond_) ;
            //解锁
            pthread_mutex_unlock(&mutex_) ;


        }

        ~BlockQueue()
        {
                pthread_mutex_destroy(&mutex_) ;
                pthread_cond_destroy(&c_cond_);
                pthread_cond_destroy(&p_cond_);

        }
    private:
    std::queue<T> q_; // 共享资源, q被当做整体使用的，q只有一份，加锁。但是共享资源也可以被看做多份！
        //int mincap_;
        int maxcap_;      // 极值
        pthread_mutex_t mutex_;  //互斥锁
        pthread_cond_t c_cond_; //消费者条件变量，用来实现同步
        pthread_cond_t p_cond_;//生产者条件变量，用来实现同步

    };